# coding=utf-8
import time

from selenium.webdriver.common.action_chains import ActionChains  # 处理鼠标事件
from Utils.logger import Log
import allure
import os.path
from selenium.webdriver.support.select import Select

# 接受logger实例
getLogger = Log("base")
log = getLogger.get_log()

"""
   定义一个页面基类，让所有页面都继承这个类，封装一些常用的页面操作方法到这个类
"""
class BasePage(object):

    u"创建一个driver对象"
    def __init__(self, driver):
        try:
            self.driver = driver
            self.driver.maximize_window()
            self.driver.implicitly_wait(10)
            log.info("浏览器启动成功")
        except Exception as e:
            log.error("浏览器启动出问题了")

    u"访问url"
    def visit(self, url):
        try:
            log.info("正在打开网址 %s 已输入" % url)
            self.driver.get(url)
            log.info("网址 %s 已输入" % url)
        except Exception as e:
            log.error("网址有问题 %s" % e)

    u"退出浏览器"
    def quit_browser(self):
        self.driver.quit()
        log.info("成功关闭浏览器")

    # 浏览器前进操作
    def forward(self):
        try:
            self.driver.forward()
            log.info("页面前进成功!!!")
        except Exception as e:
            log.error("页面前进失败 ,原因: "+str(e))

    # 页面刷新
    def refresh(self):
        try:
            self.driver.refresh()  # 刷新当前页面
            log.info("页面刷新成功!!")
        except Exception as e:
            log.error("页面刷新失败:  "+str(e))

    # 浏览器后退操作
    def back(self):
        try:
            self.driver.back()
            log.info("页面后退成功!!!")
        except Exception as e:
            log.error("页面后退失败 ,原因: "+str(e))

    # 隐式等待
    def wait(self, seconds):
        self.driver.implicitly_wait(seconds)
        log.info("设置隐式时间：%d 秒." % seconds)

    # 点击关闭当前窗口
    def close(self):
        try:
            self.driver.close()
            log.info("成功关闭当前窗口")
        except Exception as e:
            log.error("当前窗口关闭失败 原因: %s" % e)

    # 截图
    u"在这里我们把file_path这个参数写死，直接保存到我们项目根目录的一个文件夹 Screenshots下"
    def get_windows_img(self):
        # 路径相对run.py而言
        file_path = os.path.dirname(os.path.abspath('.')) + '\\mallShopping\\images\\screenshots\\'
        rq = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
        screen_name = file_path + rq + '.png'

        try:
            self.driver.get_screenshot_as_file(screen_name)
            log.info("截图成功 保存路径为: ./images/screenshots")
            self.write_img_allure(screen_name)
        except Exception as e:
            log.error("截图失败了... %s" % e)

    # 将截图保存至allure报告
    def write_img_allure(self, screen_name):
        try:
            allure.attach.file(screen_name, attachment_type=allure.attachment_type.PNG)
            log.info("截图成功了!!")
        except Exception as e:
            log.error("截图写入allure失败了, 原因: "+str(e))


    # 定位元素方法
    def find_element(self, locator):
        try:
            ele = self.driver.find_element(*locator)
            log.info("成功定位元素 %s,%s " % (locator[0], locator[1]))
            return ele
        except Exception as e:
            log.error("元素 %s,%s 查找失败, 原因: %s" % (locator[0], locator[1], str(e)))
            return False

    # 输入
    def input(self, locator, text):
        el = self.find_element(locator)
        try:
            el.clear()
            el.send_keys(text)
            log.info("向元素 %s,%s 输入框中输入内容 %s 成功" % (locator[0], locator[1], text))
            self.get_windows_img()
        except Exception as e:
            log.error("向元素 %s,%s 输入框中输入内容失败  原因: %s" % (locator[0], locator[1], str(e)))
            self.get_windows_img()

    # 清除文本框
    def clear(self, selector):

        el = self.find_element(selector)
        try:
            el.clear()
            log.info("成功清除元素 %s,%s 内容" % (selector[0], selector[1]))
        except Exception as e:
            log.error("无法用清除清除元素 %s,%s 输入框中内容,清除失败  %s" % (selector[0], selector[1], str(e)))
            self.get_windows_img()

    # 点击元素
    def click(self, locator):
        el = self.find_element(locator)
        try:
            el.click()
            self.sleep(1)
            log.info("点击元素 %s,%s 成功" % (locator[0], locator[1]))
            self.get_windows_img()
        except Exception as e:
            log.error("点击元素 %s,%s  原因: %s" % (locator[0], locator[1], str(e)))

    # 切到iframe
    def switch_frame(self, locator):
        iframe = self.find_element(locator)
        try:
            self.driver.switch_to.frame(iframe)  #原来的driver.switch_to_frame(iframe)已被弃用了
            log.info("iframe切换成功 该元素为 %s,%s " % (locator[0], locator[1]))
        except Exception as e:
            log.error("iframe切换失败  该元素为 %s,%s   %s" % (locator[0], locator[1], str(e)))

    # 切换到上一级iframe
    def quit_Switch_frame(self):
        try:
            self.driver.switch_to.parent_frame()
            log.info("成功切换到上一级iframe成功")
        except Exception as e:
            log.error("切换到上一级iframe失败"+str(e))

    # 切花到iframe主文档  即(页面上的第一个框架，或者当页面包含 iframe 时选择主文档)
    def switch_defalut(self):
        try:
            self.driver.switch_to.default_content()
            log.info("成功切换到主iframe")
        except Exception as e:
            log.error("切换到主iframe失败  原因: "+str(e))

    # 选择 select 下拉框
    def select(self, locator, select_type, content):
        try:
            ele_select = self.find_element(locator)
            if select_type == 'index':
                Select(ele_select).select_by_index(content)
            elif select_type == 'value':
                Select(ele_select).select_by_value(content)
            elif select_type == 'text':
                Select(ele_select).select_by_visible_text(content)
            else:
                log.error("不支持{},请确认Select的类型".format(select_type))
                return
            log.info("select选中成功  根据元素<{}>以 {} 方式进行下拉选择".format(locator, select_type))
        except Exception as e:
            log.error("select选中失败了  根据元素<%s>以%s方式进行下拉选择失败！原因: %s" % (locator, select_type, str(e)))

    #取消选中 select 下拉框
    def deselect(self, locator, *tc):
        ele_select = self.find_element(locator)
        try:
            if tc[0] == "all":
                Select(ele_select).deselect_all()
            elif tc[0] == "index":
                Select(ele_select).deselect_by_index(tc[1])
            elif tc[0] == "value":
                Select(ele_select).deselect_by_value(tc[1])
            elif tc[0] == "text":
                Select(ele_select).deselect_by_visible_text(tc[1])
            else:
                log.error("不支持{},请确认Select的类型".format(tc[0]))
                return
            log.info("取消选中select框成功  根据元素<{}>以 {} 方式进行取消选择".format(locator, tc[0]))
        except Exception as e:
            log.error("取消选择select失败了  根据元素<%s>以%s方式进行下拉选择失败！原因: %s" % (locator, tc[0], str(e)))

    #获取select框选中值
    def get_select(self, locator, get_select_type):
        '''
        获取select框选中值
        options                  # 返回select元素所有的options
        all_selected_options     # 返回select元素中所有已选中的选项
        first_selected_options   # 返回select元素中选中的第一个选项
        :return:
        '''
        ele_select = self.find_element(locator)
        try:
            if get_select_type == "all":
                options = Select(ele_select).options
            elif get_select_type == "select":
                options = Select(ele_select).all_selected_options
            elif get_select_type == "select_first":
                options = Select(ele_select).first_selected_option
            else:
                log.error("类型错误,你输入的类型为: %s  类型应该为 all || select || select_first" % get_select_type )
                return
            log.info("获取options成功, 你所用的获取类型为 %s" % get_select_type)
            return options
        except Exception as e:
            log.error("获取options失败了, 你所用的类型为: %s 原因: %s" %(get_select_type, str(e)))

    u"""鼠标悬停操作"""
    def move_is_element(self, locator):
        try:
            element = self.find_element(locator)
            ActionChains(self.driver).move_to_element(element).perform()
            log.info("悬停成功 该元素为 %s,%s" % (locator[0], locator[1]))
        except Exception as e:
            log.error("鼠标悬停失败 该元素为 %s,%s 原因: %s" % (locator[0], locator[1], str(e)))

    u"""获取当前窗口的title"""
    def get_title(self):
        try:
            log.info("正在获取当前窗口的 title......")
            title = self.driver.title
            log.info("成功获取当前窗口 title为:  {} ".format(title))
            return title
        except Exception as e:
            log.error("获取当前窗口 title 失败: 原因: %s" + str(e))

    u"""获取当前页面url"""
    def get_current_url(self):
        try:
            log.info("正在获取当前窗口的 url......")
            url = self.driver.current_url
            log.info("获取当前页面url成功 url为: {}".format(url))
            return url
        except Exception as e:
            log.error("获取当前窗口url失败: " + str(e))

    u"""获取文本内容"""
    def get_text(self, locator):
        try:
            log.info("正在提取元素内容......")
            text = self.find_element(locator).text
            log.info("成功从元素 %s,%s 中提取文本内容, 文本为 %s" % (locator[0], locator[1], text))
            return text
        except Exception as e:
            log.error("从元素中 %s,%s 获取内容失败 :%s" % (locator[0], locator[1], str(e)))

    u"""获取属性"""
    def get_attribute(self, locator, name):
        return self.find_element(locator).get_attribute(name)

    # 执行JS脚本
    def execute_script(self, script):
        try:
            self.driver.execute_script(script)
            log.info("js脚本执行成功")
        except Exception as e:
            log.error("js脚本执行失败  原因: "+str(e))

    u"""滑动到页面顶部"""
    def js_scroll_top(self):
        js = "window.scrollTo(0,0)"
        self.driver.execute_script(js)

    u"""滑动到页面底部"""
    def js_scroll_end(self):
        js = "window.scrollTo(0, document.body.scrollHeight)"
        self.driver.execute_script(js)

    #获取 弹窗
    def alert(self):
        try:
            alert = self.driver.switch_to.alert
            log.info("成功获取弹窗")
            return alert
        except Exception as e:
            log.error("获取弹窗失败了 原因: "+str(e))

    # 弹窗 确定
    def alert_accept(self):
        try:
            self.alert().accept()
            log.info("alert弹窗确认成功")
        except Exception as e:
            log.error("alert弹窗确认 失败!!原因: "+str(e))

    # 获取弹窗 文本值
    def alert_text(self):
        try:
            text = self.alert().text
            log.info("获取alert弹窗值 %s 成功 " % text)
            return text
        except Exception as e:
            log.error("获取alert弹窗值 失败 原因: "+str(e))

    # 取消弹窗
    def alert_dismiss(self):
        try:
            self.alert().dismiss()
            log.info("已取消alert弹窗")
        except Exception as e:
            log.error("取消alert弹窗失败!! 原因: "+str(e))

    # 弹窗 输入
    def alert_prompt(self, value):
        try:
            self.alert().send_keys(value)   # 这里输入框中看不到输入的文字  alter和confirm没有输入对话框，所以这里不能用，只能用于prompt
            log.info("成功在弹窗alert中 输入 %s" % value)
        except Exception as e:
            log.error("在alert弹窗输入值失败 原因: "+str(e))

    @staticmethod
    def sleep(seconds):
        time.sleep(seconds)
        log.info("Sleep for %d seconds" % seconds)
